package com.financial.gateway.filter;

import com.alibaba.druid.support.json.JSONUtils;
import com.financial.gateway.constants.CommonConstants;
import com.financial.gateway.constants.FinancialRoutePahtConstants;
import com.financial.gateway.utils.JsonUtils;
import com.financial.gateway.utils.RedisUtils;
import com.financial.gateway.utils.apiresult.ApiResult;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

/**
 * 自定义网关过滤器
 *
 * @auter miaozhenfei
 * @date 2019/8/8 10:12
 */
@Component
public class VisitFilter extends ZuulFilter {

    private static String separator = ",";
    //过滤url
    @Value("${gateway_ignorePath:}")
    private String ignorePath;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 过滤器顺序，越小越先执行
     */
    @Override
    public int filterOrder() {
        return 4;
    }

    /**
     * 过滤器类型，前置过滤器
     */
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    /**
     * 过滤器是否生效
     * 返回true代表需要权限校验，false代表不需要用户校验即可访问
     */
    @Override
    public boolean shouldFilter() {
        /*获取Request上下文*/
        RequestContext rc = RequestContext.getCurrentContext();
        HttpServletRequest request = rc.getRequest();
        /*判断地址类型*/
        String requestUri = request.getRequestURI();
        if (isStartWith(requestUri)) {
            /*直接过滤异步回执地址*/
            if (requestUri.contains("callback")) {
                return false;
            }
            /*获取参数解析业务类型*/
            String requestJson = JsonUtils.analysisJson(request);
            Map<String, Object> businessTypeMap = JsonUtils.jsonToMap(requestJson);
            String businessType = (String) businessTypeMap.get("business_type");
            String routePath = FinancialRoutePahtConstants.routePath(businessType);
            if (StringUtils.isNotBlank(businessType) && StringUtils.isNotBlank(routePath)) {
                /*请求转发跳转*/
                HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
                    @Override
                    public String getRequestURI() {
                        return routePath;
                    }
                };
                rc.setRequest(requestWrapper);
                return false;
            }
            setFailedRequest(ApiResult.error405(), 200);
            return false;
        }
        return true;
    }

    @Override
    public Object run() {
        RequestContext rc = RequestContext.getCurrentContext();
        HttpServletRequest request = rc.getRequest();
        String accessToken = request.getHeader(CommonConstants.CONTEXT_TOKEN);
        if (null == accessToken || accessToken == "") {
            accessToken = request.getParameter(CommonConstants.AccessToken);
            if (null == accessToken || "" == accessToken) {
                /*访问地址错误*/
                setFailedRequest(ApiResult.error401(), 200);
                return null;
            }
        } else {
            accessToken = request.getParameter(CommonConstants.AccessToken);
            if (null == accessToken || "" == accessToken) {
                /*从金融中心缓冲中获取accesstoken*/
                Object financialAccessToken = redisUtils.getValue("financialAccessToken");
                if (null == financialAccessToken) {
                    /*没有accesstoken权限控*/
                    setFailedRequest(ApiResult.error403(), 200);
                    return null;
                }
            }

        }
        return null;
    }

    private void setFailedRequest(Object body, int code) {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.setResponseStatusCode(code);
        HttpServletResponse response = ctx.getResponse();
        PrintWriter out;
        try {
            out = response.getWriter();
            out.write(JSONUtils.toJSONString(body));
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ctx.setSendZuulResponse(false);

    }

    /*循环遍历未拦截地址请求*/
    private boolean isStartWith(String requestUri) {
        boolean flag = false;
        for (String s : ignorePath.split(separator)) {

            if (requestUri.equalsIgnoreCase(s)) {
                return true;
            }
        }
        return flag;
    }
}
